package com.skyline.courier.net;

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SendFuture<V> {
	protected Logger LOGGER = LoggerFactory.getLogger(SendFuture.class);
	protected V result;
	protected AtomicBoolean done = new AtomicBoolean(false);
	protected AtomicBoolean success = new AtomicBoolean(false);
	protected Semaphore semaphore = new Semaphore(0);
	protected Throwable cause;

	public SendFuture() {
	}

	public boolean isDone() {
		return done.get();
	}

	public V getResult() throws Throwable {
		if (!isDone()) {
			try {
				semaphore.acquire();
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			}
		}
		// check exception
		if (cause != null) {
			throw cause;
		}
		//
		return this.result;
	}

	public void setResult(V result) {
		this.result = result;
		done.set(true);
		success.set(true);

		semaphore.release(Integer.MAX_VALUE - semaphore.availablePermits());
	}

	public V getResult(long timeout, TimeUnit unit) throws Throwable {
		if (!isDone()) {
			try {
				if (!semaphore.tryAcquire(timeout, unit)) {
					setCause(new RuntimeException("接收消息超时"));
				}
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			}
		}
		// check exception
		if (cause != null) {
			throw cause;
		}
		//
		return this.result;
	}

	public void setCause(Throwable cause) {
		this.cause = cause;
		done.set(true);
		success.set(false);
		semaphore.release(Integer.MAX_VALUE - semaphore.availablePermits());
	}

	public boolean isSuccess() {
		return success.get();
	}

	public Throwable getCause() {
		return cause;
	}

}
